#include "uln2003.h"
#include "gpio.h"
#include "main.h"
#include <stdint.h>

#define MOTOR_STEP (1000u) /**< 电机执行圈数*/

/**
 * @brief uln2003专用延时函数
 * @param  time             us
 */
void Delay_us(uint16_t time) // Delay_us(0) = 10.2us
{
	HAL_SYSTICK_Config(72);
	HAL_Delay(time);
	HAL_SYSTICK_Config(7200);
}

/************************************************
延时：
ULN_Delay_Forward:
控制正转速 100~500
ULN_Delay_Reverse
控制反转速 50~200
************************************************/
#define ULN_delay Delay_us
#define ULN_Delay_Forward 150
#define ULN_Delay_Reverse 120

// GPIO输出电平，lv只能输入0或1，没有错误检测，使用小心
#define IN0_LEVEL(lv) HAL_GPIO_WritePin(MOTOR1_GPIO_Port, MOTOR1_Pin, (lv))
#define IN1_LEVEL(lv) HAL_GPIO_WritePin(MOTOR2_GPIO_Port, MOTOR2_Pin, (lv))
#define IN2_LEVEL(lv) HAL_GPIO_WritePin(MOTOR3_GPIO_Port, MOTOR3_Pin, (lv))
#define IN3_LEVEL(lv) HAL_GPIO_WritePin(MOTOR4_GPIO_Port, MOTOR4_Pin, (lv))

// 电机状态控制
#define AHighLevel IN0_LEVEL(1), IN1_LEVEL(0), IN2_LEVEL(0), IN3_LEVEL(0)
#define BHighLevel IN0_LEVEL(0), IN1_LEVEL(1), IN2_LEVEL(0), IN3_LEVEL(0)
#define CHighLevel IN0_LEVEL(0), IN1_LEVEL(0), IN2_LEVEL(1), IN3_LEVEL(0)
#define DHighLevel IN0_LEVEL(0), IN1_LEVEL(0), IN2_LEVEL(0), IN3_LEVEL(1)

#define ABHighLevel IN0_LEVEL(1), IN1_LEVEL(1), IN2_LEVEL(0), IN3_LEVEL(0)
#define BCHighLevel IN0_LEVEL(0), IN1_LEVEL(1), IN2_LEVEL(1), IN3_LEVEL(0)
#define CDHighLevel IN0_LEVEL(0), IN1_LEVEL(0), IN2_LEVEL(1), IN3_LEVEL(1)
#define DAHighLevel IN0_LEVEL(1), IN1_LEVEL(0), IN2_LEVEL(0), IN3_LEVEL(1)

// 电机控制
#define StopIt IN0_LEVEL(0), IN1_LEVEL(0), IN2_LEVEL(0), IN3_LEVEL(0) // 停止
#define Brake IN0_LEVEL(1), IN1_LEVEL(1), IN2_LEVEL(1), IN3_LEVEL(1)  // 刹车

#define Forward                       \
	do                                \
	{                                 \
		AHighLevel;                   \
		ULN_delay(ULN_Delay_Forward); \
		ABHighLevel;                  \
		ULN_delay(ULN_Delay_Forward); \
		BHighLevel;                   \
		ULN_delay(ULN_Delay_Forward); \
		BCHighLevel;                  \
		ULN_delay(ULN_Delay_Forward); \
		CHighLevel;                   \
		ULN_delay(ULN_Delay_Forward); \
		CDHighLevel;                  \
		ULN_delay(ULN_Delay_Forward); \
		DHighLevel;                   \
		ULN_delay(ULN_Delay_Forward); \
		DAHighLevel;                  \
		ULN_delay(ULN_Delay_Forward); \
	} while (0)

#define Reverse                       \
	do                                \
	{                                 \
		DHighLevel;                   \
		ULN_delay(ULN_Delay_Reverse); \
		CDHighLevel;                  \
		ULN_delay(ULN_Delay_Reverse); \
		CHighLevel;                   \
		ULN_delay(ULN_Delay_Reverse); \
		BCHighLevel;                  \
		ULN_delay(ULN_Delay_Reverse); \
		BHighLevel;                   \
		ULN_delay(ULN_Delay_Reverse); \
		ABHighLevel;                  \
		ULN_delay(ULN_Delay_Reverse); \
		AHighLevel;                   \
		ULN_delay(ULN_Delay_Reverse); \
		DAHighLevel;                  \
		ULN_delay(ULN_Delay_Reverse); \
	} while (0)

/************************************************
输出一次步进电机的运动
STOP_IT 停止
BRAKE 	刹车
FORWARD 向前
REVERSE 反转
************************************************/
void uln2003_MotorRotation(RotationSTATE rotationControl)
{
	switch (rotationControl)
	{
	case STOP_IT:
		StopIt;
		break;
	case BRAKE:
		Brake;
		break;
	case FORWARD:
		Forward;
		break;
	case REVERSE:
		Reverse;
		break;
	default:
		StopIt;
		break;
	}
}

/**
 * @brief 电机入口函数
 */
void motor_entry(void)
{
	for (uint32_t i = 0; i < MOTOR_STEP; i++) /**< 正转指定圈数*/
	{
		uln2003_MotorRotation(FORWARD);
	}
	HAL_Delay(5000);						  /**< 指定延时时间*/
	for (uint32_t i = 0; i < MOTOR_STEP; i++) /**< 反转指定圈数*/
	{
		uln2003_MotorRotation(FORWARD);
	}
	uln2003_MotorRotation(FORWARD); /**< 需要停止，防止线圈长时间通电*/
}
/* EOF */
